import { useConfigStore } from "./config";
import { useMasterStore } from "./master";
import type { Storage } from "./master/types";
import { useAsyncRef } from "@/utils/use";
import { defineStore } from "pinia";
import { computed, reactive } from "vue";

export const useStorageStore = defineStore("storage", () => {
  const masterStore = useMasterStore();
  const configStore = useConfigStore();

  const ids = useAsyncRef({
    supplier: async () => {
      const hosts = configStore.cache.config.value!.hosts;
      const hostIds = new Set(hosts.map((host) => host.id));
      const storageIds = await masterStore.getStorageIds();
      return {
        valid: storageIds.filter((id) => hostIds.has(id)),
        invalid: storageIds.filter((id) => !hostIds.has(id)),
      };
    },
  });
  const cache = reactive<Record<string, Storage | null | undefined>>({});

  const timer = { count: 0, timestamp: 0 };
  (async function poll() {
    const now = Date.now();
    if (timer.count > 0 && now - timer.timestamp > 60000) {
      timer.timestamp = now;
      for (const { id } of configStore.config?.hosts ?? []) {
        try {
          cache[id] = await masterStore.getStorage(id);
        } catch (error) {}
      }
    }
    setTimeout(poll, 1000);
  })();

  async function gc() {
    await ids.execute({
      onState: { ready: true },
      supplier: async () => {
        const invalid = [...ids.value.value!.invalid];
        try {
          while (invalid.length > 0) {
            await masterStore.deleteStorage(invalid[0]);
            invalid.splice(0, 1);
          }
        } finally {
          return { valid: ids.value.value!.valid, invalid };
        }
      },
    });
  }

  function $reset() {
    ids.reset();
    for (const key of Object.keys(cache)) {
      delete cache[key];
    }
  }

  return {
    cache,
    ids: computed(ids.view),
    gc,
    fetchIds: ids.execute,
    startTimer: () => timer.count++,
    stopTimer: () => timer.count--,
    $reset,
  };
});
